﻿using System.Collections.Generic;
using System.Diagnostics;
using System.Web.Mvc;
using BLL.Services;
using BLL.Services.Categories;
using BLL.Services.Categories.Listing;
using MvcContrib.Sorting;
using MvcContrib.UI.Grid;
using Web.Areas.Admin.Infrastructure;
using Web.Areas.Admin.Models.Categories;
using Web.Infrastructure;
using Web.Infrastructure.Models;
using Web.Infrastructure.Security;

namespace Web.Areas.Admin.Controllers
{
    /// <summary>
    /// Controller for category management
    /// </summary>
    [AdminAuthorization]
    public partial class CategoriesController : AdminController
    {
        private readonly ICategoriesService _categoriesService;

        /// <summary>
        /// Initializes a new instance of the <see cref="CategoriesController" /> class.
        /// </summary>
        /// <param name="categoriesService">The categories service.</param>
        public CategoriesController(ICategoriesService categoriesService)
        {
            _categoriesService = categoriesService;
        }

        /// <summary>
        /// Return empty view for synchronize with client routes
        /// </summary>
        public virtual ActionResult Index()
        {
            return View(MVC.Admin.Shared.Views.Empty);
        }

        /// <summary>
        /// Listings the template.
        /// </summary>
        public virtual ActionResult ListingTemplate()
        {
            return BackBoneView(MVC.Admin.Categories.Views.Listing);
        }

        /// <summary>
        /// Listings the specified sort.
        /// </summary>
        /// <param name="sort">The sort.</param>
        /// <param name="size">The size.</param>
        /// <param name="page">The page.</param>
        /// <param name="filter">The filter.</param>
        [ListingAction("Name")]
        public virtual ActionResult Listing(GridSortOptions sort, int size, int page, CategoryFilter filter)
        {
            var model = _categoriesService.GetCategoryListing(
                page, size, sort.Column, sort.Direction != SortDirection.Descending ? 0 : 1, filter);
            return BackBoneJson(model);
        }

        /// <summary>
        /// Deletes selected items.
        /// </summary>
        /// <param name="items">Items to delete.</param>
        public virtual ActionResult Delete(int[] items)
        {
            var model = new BaseModel();
            foreach (var item in items)
            {
                try
                {
                    _categoriesService.Delete(item);
                }
                catch (ServiceException exception)
                {
                    ModelState.AddModelError(string.Empty, "Could not delete category with id: " + item);
                    Trace.TraceError(exception.ToString());
                }
            }
            model.Errors = GetErrors;
            if (ModelState.IsValid)
            {
                model.SuccessMessage = "Category have been successfully deleted.";
            }
            return Json(model);
        }

        /// <summary>
        /// Show form for create category
        /// </summary>
        [HttpGet]
        public virtual ActionResult Create()
        {
            return BackBoneView(MVC.Admin.Shared.Views.Empty);
        }

        /// <summary>
        /// Creates the template.
        /// </summary>
        public virtual ActionResult CreateTemplate()
        {
            return BackBoneView(MVC.Admin.Categories.Views.Create, new CategoriesCreateModel());
        }

        /// <summary>
        /// Creates the specified model.
        /// </summary>
        /// <param name="model">The model.</param>
        [HttpPost]
        public virtual ActionResult Create(CategoriesCreateModel model)
        {
            if (!ModelState.IsValid)
            {
                model.Errors = GetErrors;
                return Json(model);
            }
            var category = (Category)model;
            try
            {
                _categoriesService.Create(category);
                model.SuccessMessage = "Category has been successfully created.";
                return Json(model);
            }
            catch (ServiceException exception)
            {
                ModelState.AddModelError(string.Empty, exception.Message);
                model.Errors = GetErrors;
                return Json(model);
            }
        }

        /// <summary>
        /// Show form for editing the specified category.
        /// </summary>
        /// <param name="categoryId">The category id.</param>
        [HttpGet]
        public virtual ActionResult Edit(int? categoryId)
        {
            var model = new CategoriesEditModel();
            if (!categoryId.HasValue)
            {
                model.Errors = new List<ErrorModel>
                    {
                        new ErrorModel("Empty value")
                    };
                return BackBoneJson(model);
            }
            var category = _categoriesService.GetCategoryById(categoryId.Value);

            if (null == category)
            {
                model.Errors = new List<ErrorModel>
                    {
                        new ErrorModel(string.Format("Category {0} was not found.", categoryId))
                    };
                return BackBoneJson(new CategoriesEditModel());
            }

            model = new CategoriesEditModel(category);

            return BackBoneJson(model);
        }

        /// <summary>
        /// Edits the template.
        /// </summary>
        public virtual ActionResult EditTemplate()
        {
            return PartialView(MVC.Admin.Categories.Views.Edit, new CategoriesEditModel());
        }

        /// <summary>
        /// Save the specified category.
        /// </summary>
        /// <param name="categoryId">The category id.</param>
        /// <param name="model">The model.</param>
        [HttpPost]
        public virtual ActionResult Edit(int categoryId, CategoriesEditModel model)
        {
            if (!ModelState.IsValid)
            {
                model.Errors = GetErrors;
                return Json(model);
            }

            var category = (Category)model;
            try
            {
                _categoriesService.Save(category);

                model.SuccessMessage = "Category has been successfully updated.";

                return Json(model);
            }
            catch (ServiceException exception)
            {
                ModelState.AddModelError(string.Empty, exception.Message);
                model.Errors = GetErrors;
                return Json(model);
            }
        }

        /// <summary>
        /// Validates the specified category id.
        /// </summary>
        /// <param name="categoryId">The category id.</param>
        /// <param name="name">The name.</param>
        public virtual ActionResult Validate(int? categoryId, string name)
        {
            var idParam = categoryId.HasValue ? categoryId.Value : 0;
            var result = _categoriesService.ValidateCategory(idParam, name);
            return Json(result);
        }
    }
}